<!--
  文件级注释：分账记录详情页面
  - 展示指定分账记录的详情列表
  - 查询并渲染完整分账树（默认展开）
  规则：接口返回值 code === 0 视为成功
-->

<template>
  <div class="container">
    <div class="header">
      <h1>分账记录详情</h1>
      <router-link class="btn" to="/divided-records">返回记录列表</router-link>
    </div>

    <!-- 基本信息 -->
    <div class="card">
      <div class="row"><span class="label">记录ID：</span><span>{{ recordId }}</span></div>
      <div class="row"><span class="label">订单ID：</span><span>{{ base?.orderId || '-' }}</span></div>
      <div class="row"><span class="label">协议ID：</span><span>{{ base?.dividedAgreementId || '-' }}</span></div>
      <div class="row"><span class="label">分账日期：</span><span>{{ formatYMD(base?.dividedDate) }}</span></div>
      <div class="row"><span class="label">创建时间：</span><span>{{ base?.creationTime || '-' }}</span></div>
    </div>

    <!-- 详情列表 -->
    <div class="section">
      <div class="section-header">
        <h2>分账详情列表</h2>
        <button class="btn" @click="fetchDetails">刷新列表</button>
      </div>
      <table class="table">
        <thead>
          <tr>
            <th>明细ID</th>
            <th>用户ID</th>
            <th>手机号</th>
            <th>分账比例</th>
            <th>分账金额</th>
            <th>角色ID</th>
            <th>是否主账号</th>
            <th>创建时间</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="d in details" :key="d.id">
            <td>{{ d.id || '-' }}</td>
            <td>{{ d.userId || '-' }}</td>
            <td>{{ d.userPhone || '-' }}</td>
            <td>{{ d.ratio ?? '-' }}</td>
            <td>{{ formatCents(d.dividedAmount) }}</td>
            <td>{{ d.userRoleId || '-' }}</td>
            <td>{{ d.isMasterAccount ? '是' : '否' }}</td>
            <td>{{ d.creationTime || '-' }}</td>
          </tr>
          <tr v-if="details.length === 0"><td colspan="8" class="empty">暂无详情</td></tr>
        </tbody>
      </table>
    </div>

    <!-- 完整分账树（默认展开） -->
    <div class="section">
      <div class="section-header">
        <h2>完整分账树</h2>
        <div class="controls">
          <button class="btn" @click="fetchFullTree">刷新树</button>
          <button class="btn" @click="setMaxLevel(1)">折叠到一级</button>
          <button class="btn" @click="setMaxLevel(2)">展开到二级</button>
          <button class="btn" @click="setMaxLevel(999)">展开全部</button>
        </div>
      </div>
      <table class="table">
        <thead>
          <tr>
            <th>节点名称</th>
            <th>层级</th>
            <th>分账比例</th>
            <th>分账金额</th>
            <th>路径</th>
            <th>关联信息</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="node in flatTreeVisible" :key="node.id">
            <td>
              <div class="tree-item">
                <span :class="['type-badge', node.type === 'agreement' ? 'type-agreement' : 'type-participant']">
                  {{ node.type === 'agreement' ? '协议' : '参与人' }}
                </span>
                <span class="level-badge">L{{ node.level }}</span>
                <span class="node-label" :style="{ paddingLeft: `${node.level * 12}px` }">{{ node.label || '-' }}</span>
              </div>
            </td>
            <td>{{ node.level }}</td>
            <td>{{ node.ratio ?? '-' }}</td>
            <td>{{ formatCents(node.amount) }}</td>
            <td class="path-cell">{{ formatPath(node.path) }}</td>
            <td>{{ node.extra || '-' }}</td>
          </tr>
          <tr v-if="flatTree.length === 0"><td colspan="4" class="empty">暂无树形数据</td></tr>
        </tbody>
      </table>
    </div>

    <!-- 图形化分账树（SVG+卡片） -->
    <div class="section">
      <div class="section-header">
        <h2>图形树</h2>
        <button class="btn" @click="fetchFullTree">刷新图形树</button>
      </div>
      <DividedTree :data="treeArray" :nodeWidth="180" :nodeHeight="88" :hGap="40" :vGap="60" />
    </div>
  </div>
  
</template>

<script setup lang="ts">
import { onMounted, ref, computed } from 'vue'
import { useRoute } from 'vue-router'
import { DividedService } from '../services/divided'
import { isSuccess } from '../services/types'
import DividedTree from '../components/DividedTree.vue'

/** 类级注释：分账记录详情视图组件 */

/** 路由与记录ID */
const route = useRoute()
/**
 * 参数注释：记录ID（来自路由 param）
 * 类型：string
 */
const recordId = ref<string>(String(route.params.id || route.path.split('/').pop() || ''))

/** 基本信息 */
const base = ref<any | null>(null)
/** 详情列表 */
const details = ref<any[]>([])
/** 树形原始数据 */
const tree = ref<any | null>(null)
/** 展开渲染使用的扁平数组（完整） */
const flatTree = computed<any[]>(() => flattenTree(tree.value))
/** 图形树需要的数组根 */
const treeArray = computed<any[]>(() => Array.isArray(tree.value) ? tree.value : (tree.value ? [tree.value] : []))
/** 可见层级上限 */
const visibleMaxLevel = ref<number>(999)
/** 依据层级过滤后的扁平数组 */
const flatTreeVisible = computed<any[]>(() => flatTree.value.filter(n => n.level <= visibleMaxLevel.value))

/**
 * 函数级注释：拉取记录根层基本信息（可选）
 * @returns Promise<void>
 * @throws 可能抛出网络异常
 */
async function fetchBase(): Promise<void> {
  const res = await DividedService.getDividedRecordRootLayer(recordId.value)
  if (isSuccess(res)) {
    const d: any = res.data || {}
    base.value = {
      id: d.Id ?? d.id ?? recordId.value,
      orderId: d.OrderId ?? d.orderId ?? '',
      dividedAgreementId: d.DividedAgreementId ?? d.dividedAgreementId ?? '',
      dividedDate: d.DividedDate ?? d.dividedDate ?? '',
      creationTime: d.CreationTime ?? d.creationTime ?? ''
    }
  } else {
    // 非致命：根层信息失败不影响详情与树渲染
    console.warn('获取根层信息失败：', res.message)
  }
}

/**
 * 函数级注释：拉取分账详情列表
 * @returns Promise<void>
 * @throws 可能抛出网络异常
 */
async function fetchDetails(): Promise<void> {
  const res = await DividedService.getDividedRecordDetailList(recordId.value)
  if (isSuccess(res)) {
    const arr: any[] = Array.isArray(res.data) ? res.data : []
    details.value = arr.map((d: any) => ({
      id: d.Id ?? d.id ?? '',
      userId: d.UserId ?? d.userId ?? '',
      userPhone: d.UserPhone ?? d.userPhone ?? '',
      ratio: d.Ratio ?? d.ratio ?? undefined,
      dividedAmount: d.DividedAmount ?? d.dividedAmount ?? undefined,
      userRoleId: d.UserRoleId ?? d.userRoleId ?? '',
      isMasterAccount: d.IsMasterAccount ?? d.isMasterAccount ?? false,
      creationTime: d.CreationTime ?? d.creationTime ?? ''
    }))
  } else {
    alert(res.message || '获取分账详情失败')
  }
}

/**
 * 函数级注释：拉取完整分账树（基于静态快照比例）
 * @returns Promise<void>
 * @throws 可能抛出网络异常
 */
async function fetchFullTree(): Promise<void> {
  const res = await DividedService.getDividedRecordFullTreeByOrderId(undefined, recordId.value)
  if (isSuccess(res)) {
    // 参数/返回值注释：后端返回 data 中包含 Tree 数组（AgreementTreeNode[]）
    // 这里将 DTO 结构归一化为通用树格式以供前端渲染
    const dto = (res as any).data || {}
    const treeDto = dto.Tree || dto.tree || []
    tree.value = normalizeFullTreeFromDto(treeDto)
  } else {
    alert(res.message || '获取完整分账树失败')
  }
}

/**
 * 函数级注释：将后端树形数据规范化为统一结构（兼容数组/对象根）
 * @param raw 任意后端返回数据（可能是对象或数组）
 * @returns any 统一结构：
 *  - 若为对象：{ id,label,ratio,amount,extra,children[] }
 *  - 若为数组：归一化后的对象数组
 * 异常：无显式异常（空或非法结构返回 null 或空数组）
 */
function normalizeTree(raw: any): any {
  if (!raw) return null
  // 后端可能直接返回根节点数组，需兼容
  if (Array.isArray(raw)) {
    return raw.map((item: any) => normalizeTree(item)).filter(Boolean)
  }
  // 兼容多种子节点字段名
  const childrenSrc =
    raw.Children || raw.children || raw.Nodes || raw.nodes || raw.Childs || raw.childs || raw.Items || raw.items || []
  const norm = {
    id: raw.Id ?? raw.id ?? raw.NodeId ?? raw.nodeId ?? '',
    label:
      raw.NodeName ??
      raw.nodeName ??
      raw.UserName ??
      raw.userName ??
      raw.CodeName ??
      raw.codeName ??
      raw.Name ??
      raw.name ??
      '',
    ratio: raw.Ratio ?? raw.ratio ?? raw.Rate ?? raw.rate ?? undefined,
    amount: raw.DividedAmount ?? raw.dividedAmount ?? raw.Amount ?? raw.amount ?? undefined,
    extra:
      raw.UserId
        ? `用户:${raw.UserId}`
        : raw.CodeId
        ? `码:${raw.CodeId}`
        : raw.OrderId
        ? `订单:${raw.OrderId}`
        : '',
    children: Array.isArray(childrenSrc) ? childrenSrc.map((c: any) => normalizeTree(c)).filter(Boolean) : []
  }
  return norm
}

/**
 * 函数级注释：基于后端 DTO（AgreementTreeNode[]）规范化为前端通用树结构
 * @param treeDto 来自接口 data.Tree 的数组或对象
 * @returns any[] 统一结构数组：[{ id,label,ratio,amount,extra,children[] }]
 * 异常：无显式异常（空入参返回空数组）
 */
function normalizeFullTreeFromDto(treeDto: any): any[] {
  const arr = Array.isArray(treeDto) ? treeDto : (treeDto ? [treeDto] : [])
  return arr.map((n: any) => normalizeAgreementNodeFromDto(n)).filter(Boolean)
}

/**
 * 函数级注释：将 AgreementTreeNode 归一化
 * @param node AgreementTreeNode（字段：AgreementId,AgreementName,AccRatio,AccAmount,Participants[]）
 * @returns any 通用树结构节点
 */
function normalizeAgreementNodeFromDto(node: any): any {
  if (!node) return null
  const participants = Array.isArray(node.Participants || node.participants) ? (node.Participants || node.participants) : []
  const children = participants.map((p: any) => normalizeParticipantNodeFromDto(node, p)).filter(Boolean)
  return {
    id: node.AgreementId ?? node.agreementId ?? '',
    label: node.AgreementName ?? node.agreementName ?? '',
    ratio: node.AccRatio ?? node.accRatio ?? undefined,
    amount: node.AccAmount ?? node.accAmount ?? undefined,
    extra: '协议层',
    type: 'agreement',
    children
  }
}

/**
 * 函数级注释：将 ParticipantTreeNode 归一化为通用树结构，并衔接其 SubLayer
 * @param parent 上层协议节点（用于生成唯一ID前缀）
 * @param p ParticipantTreeNode（字段：UserId,UserName,Phone,Ratio,Amount,HasSubAgreement,SubAgreementId,SubLayer）
 * @returns any 通用树结构节点
 */
function normalizeParticipantNodeFromDto(parent: any, p: any): any {
  if (!p) return null
  const hasSub = (p.HasSubAgreement ?? p.hasSubAgreement) === true
  const subLayer = p.SubLayer ?? p.subLayer
  const child = subLayer ? normalizeAgreementNodeFromDto(subLayer) : null
  return {
    id: `${parent.AgreementId ?? parent.agreementId}|${p.UserId ?? p.userId ?? ''}`,
    label: (p.UserName ?? p.userName ?? p.UserId ?? p.userId ?? '') + (p.Phone ? `(${p.Phone})` : ''),
    ratio: p.Ratio ?? p.ratio ?? undefined,
    amount: p.Amount ?? p.amount ?? undefined,
    extra: hasSub ? `参与人有子协议(${p.SubAgreementId ?? p.subAgreementId ?? ''})` : '参与人',
    omitted: hasSub && !child,
    type: 'participant',
    children: child ? [child] : []
  }
}

/**
 * 函数级注释：扁平化树形结构用于表格渲染（兼容数组/对象根，默认展开）
 * @param root 根节点或根节点数组
 * @returns any[] 带有 level 的扁平数组
 * 异常：无显式异常（空入参返回空数组）
 */
function flattenTree(root: any): any[] {
  const out: any[] = []
  if (!root) return out
  const dfs = (n: any, level: number, pathArr: string[]) => {
    if (!n) return
    const pathNext = [...pathArr, n.label || '-']
    out.push({ id: n.id, label: n.label, ratio: n.ratio, amount: n.amount, extra: n.extra, level, type: n.type || 'node', path: pathNext })
    if (Array.isArray(n.children)) {
      for (const c of n.children) dfs(c, level + 1, pathNext)
    }
  }
  const roots = Array.isArray(root) ? root : [root]
  for (const r of roots) dfs(r, 0, [])
  return out
}

/**
 * 函数级注释：设置可见层级上限
 * @param level 显示到的最大层级（0为根层）
 * @returns void 无返回值
 * 异常：无显式异常
 */
function setMaxLevel(level: number): void {
  visibleMaxLevel.value = level
}

/**
 * 函数级注释：格式化路径为可读字符串
 * @param path 路径数组（从根到当前）
 * @returns string 用“→”连接的路径字符串；空数组返回 '-'
 * 异常：无显式异常
 */
function formatPath(path?: string[]): string {
  if (!path || path.length === 0) return '-'
  return path.join(' → ')
}

/**
 * 函数级注释：格式化字符串/日期为 年-月-日 展示
 * @param d 日期字符串或 Date
 * @returns string 形如 YYYY-MM-DD；入参为空时返回 '-'
 * @throws 无显式异常（非法输入返回 '-'）
 */
function formatYMD(d?: string | Date | null): string {
  if (!d) return '-'
  const dt = typeof d === 'string' ? new Date(d) : d
  if (isNaN(dt.getTime())) return '-'
  const pad = (n: number) => String(n).padStart(2, '0')
  return `${dt.getFullYear()}-${pad(dt.getMonth() + 1)}-${pad(dt.getDate())}`
}

/**
 * 函数级注释：格式化金额（分）为人民币元显示
 * @param v 金额（分，number 或可转为 number）
 * @returns 字符串，形如 `¥123.45`；空值或非法值返回 "-"
 * @throws 无显式异常（内部做 NaN 防御）
 */
function formatCents(v?: number): string {
  if (v === null || v === undefined) return '-'
  const n = Number(v)
  if (Number.isNaN(n)) return '-'
  return `¥${(n / 100).toFixed(2)}`
}

onMounted(async () => {
  await fetchBase()
  await fetchDetails()
  await fetchFullTree()
})
</script>

<style scoped>
.container { display: grid; gap: 16px; }
.header { display: flex; justify-content: space-between; align-items: center; }
.btn { height: 32px; padding: 0 12px; border: 1px solid var(--border); background: var(--bg-secondary); border-radius: 6px; cursor: pointer; }
.card { display: grid; gap: 8px; padding: 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--card-bg); }
.row { display: flex; gap: 12px; }
.label { color: var(--text-secondary); width: 120px; }
.section { display: grid; gap: 8px; }
.section-header { display: flex; justify-content: space-between; align-items: center; }
.controls { display: flex; gap: 8px; }
.table { width: 100%; border-collapse: collapse; }
.table th, .table td { padding: 10px; border-bottom: 1px solid var(--border); text-align: left; }
.empty { text-align: center; color: var(--text-secondary); }

/* 树形视觉增强 */
.tree-item { display: flex; align-items: center; gap: 8px; }
.type-badge { font-size: 12px; padding: 2px 6px; border-radius: 6px; color: #fff; }
.type-agreement { background: #4a90e2; }
.type-participant { background: #7ed321; }
.level-badge { font-size: 12px; padding: 2px 6px; border-radius: 6px; background: #f0f0f0; color: #333; }
.node-label { font-weight: 500; }
.path-cell { color: var(--text-secondary); font-size: 12px; }
</style>
